﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Media;
using Styx;
using Styx.Common;
using Styx.CommonBot;
using Styx.Helpers;
using Styx.MemoryManagement;
using Styx.Plugins;
using Talented.Forms;
using Styx.WoWInternals;

namespace Talented
{
    public class Talented : HBPlugin
    {
        #region Non-HB Specific

        private static bool HasLearnedMajorTree { get { return CurrentSpecialization > 0; } }

        private static int CurrentSpecialization { get { return Lua.GetReturnVal<int>("return GetSpecialization()", 0); } }

        public void SetSpecialization(string name, int index)
        {
            Logging.Write(Colors.LawnGreen, "[Talented2] Setting class specialization to {0} [Index: {1}]", name, index);
            Lua.DoString("SetSpecialization({0})", index);
        }

        private static void LearnTalent(int tier, int index)
        {
            Lua.DoString(string.Format("LearnTalent({0})", (tier - 1) * 3 + index));
        }

        private static IEnumerable<TalentPlacement> BuildLearnedTalents()
        {
            var ret = new List<TalentPlacement>();

            using (StyxWoW.Memory.AcquireFrame())
            {
                for (int tierIndex = 0; tierIndex < 6; tierIndex++)
                {
                    for (int talentIndex = 1; talentIndex <= 3; talentIndex++)
                    {
                        var index = tierIndex * 3 + talentIndex;
                        var vals = Lua.GetReturnValues("return GetTalentInfo(" + index + ")");
                        var name = vals[0];
                        var learned = int.Parse(vals[4]) != 0;

                        if (learned)
                        {
                            ret.Add(new TalentPlacement(tierIndex + 1, talentIndex, name));
                        }
                    }
                }
            }

            return ret;
        }

        private void InitializeHooks()
        {
            BotEvents.Player.OnLevelUp += Player_OnLevelUp;
        }

        private void Player_OnLevelUp(BotEvents.Player.LevelUpEventArgs args)
        {
            using (StyxWoW.Memory.AcquireFrame())
            {
                if (StyxWoW.Me.Level < 10)
                    return;

                if (!HasLearnedMajorTree)
                {
                    SetSpecialization(_talentBuild.BuildName, _talentBuild.Specialization);
                }
                else if (CurrentSpecialization != _talentBuild.Specialization)
                {
                    Logging.Write(Colors.Red, "[Talented2] Your currrent talent specialization doesn't fit to the selected talent build. Please change it from Plugin settings.");
                    return;
                }

                var learned = BuildLearnedTalents().ToList();
                var wanted = _talentBuild.TalentPlacements;

                foreach (var tp in wanted)
                {
                    // If our level is lower then needed level for this tier skip it.
                    if (StyxWoW.Me.Level < tp.Tier * 15)
                        continue;

                    // If there is any talents learned in this tier skip it
                    var isLearned = learned.Any(lt => lt.Tier == tp.Tier);

                    if (!isLearned)
                    {
                        Logging.Write(Colors.LawnGreen, "[Talented2] Learning talent {0} [Tier: {1} Index: {2}]", tp.Name, tp.Tier, tp.Index);
                        LearnTalent(tp.Tier, tp.Index);
                    }
                }
            }
        }

        #endregion

        private TalentTree _talentBuild;
        private bool _buildFailed;
        private bool _initialized;
        public override void Pulse()
        {
            if (TalentedSettings.Instance.FirstUseAfterChange)
            {
                Logging.Write(Colors.Red, "[Talented2] There has been some structure changes in talented. You need to (re)set a talent build from settings.");
                return;
            }

            if (_talentBuild == null || _talentBuild.BuildName != TalentedSettings.Instance.ChoosenTalentBuildName || _talentBuild.Class != TalentedSettings.Instance.ChoosenTalentClass)
            {
                try
                {
                    _talentBuild = TalentedSettings.Instance.ChoosenTalentBuild;
                    _buildFailed = false;

                    if (_talentBuild != null)
                        Logging.Write(Colors.LawnGreen, "[Talented2] Using talent build: {0}-{1}", _talentBuild.Class, _talentBuild.BuildName);
                }
                catch (Exception ex)
                {
                    if (_buildFailed)
                        return;

                    _buildFailed = true;
                    Logging.Write(Colors.Red, "[Talented2] One or more talent builds couldn't be parsed successfully. Please repair the talent build files in Data/Talent Builds folder. Exception:", ex.Message);
                    return;
                }
            }

            if (_talentBuild == null)
            {
                Logging.Write(Colors.Red, "[Talented2] You have not yet selected a talent build! Please open the form and select one");
                return;
            }



            if (_talentBuild != null && _talentBuild.Class != StyxWoW.Me.Class && StyxWoW.Me.Level > 0)
            {
                Logging.Write(Colors.Red, "[Talented2] This build is not meant for you class! Please select another talent build");
                return;
            }

            if (!_initialized)
            {
                InitializeHooks();
                Player_OnLevelUp(null);
                _initialized = true;
            }
        }

        public override void Dispose()
        {
            BotEvents.Player.OnLevelUp -= Player_OnLevelUp;
        }

        public override string Name { get { return "Talented2"; } }

        public override string Author { get { return "Apoc/Nesox/Raphus"; } }

        public override Version Version { get { return new Version(2, 0, 0); } }

        public override bool WantButton { get { return true; } }

        public override string ButtonText { get { return "Select Talent Build"; } }

        public override void OnButtonPress()
        {
            var config = new FormConfig();
            config.ShowDialog();
        }
    }
}
